package com.example.blog.service.impl;

import com.example.blog.dto.UserAdminDTO;

import com.example.blog.entity.User;
import com.example.blog.exception.ResourceNotFoundException;
import com.example.blog.modules.user.entity.Role;
import com.example.blog.modules.user.repository.RoleRepository;
import com.example.blog.repository.ArticleRepository;
import com.example.blog.repository.CommentRepository;

import com.example.blog.repository.UserRepository;
import com.example.blog.service.UserAdminService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class UserAdminServiceImpl implements UserAdminService {
    @Autowired
    private UserRepository userRepository;

    @Autowired
    private RoleRepository roleRepository;

    @Autowired
    private ArticleRepository articleRepository;

    @Autowired
    private CommentRepository commentRepository;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public Page<UserAdminDTO> getAllUsers(String keyword, Pageable pageable) {
        if (keyword != null && !keyword.isEmpty()) {
            return userRepository.findByUsernameContainingOrEmailContainingOrNicknameContaining(
                    keyword, keyword, keyword, pageable).map(this::convertToAdminDTO);
        }
        return userRepository.findAll(pageable).map(this::convertToAdminDTO);
    }

    @Override
    public UserAdminDTO getUserById(Long id) {
        return userRepository.findById(id)
                .map(this::convertToAdminDTO)
                .orElseThrow(() -> new ResourceNotFoundException("User", "id", id));
    }

    @Override
    @Transactional
    public UserAdminDTO updateUser(Long id, UserAdminDTO userDTO) {
        User user = userRepository.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("User", "id", id));

        user.setNickname(userDTO.getNickname());
        user.setEmail(userDTO.getEmail());
        user.setAvatar(userDTO.getAvatar());
        user.setBio(userDTO.getBio());
        user.setEnabled(userDTO.isEnabled());

        return convertToAdminDTO(userRepository.save(user));
    }

    @Override
    @Transactional
    public void deleteUser(Long id) {
        User user = userRepository.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("User", "id", id));

        // 检查是否为超级管理员
        if (user.getRoles().stream().anyMatch(role -> role.getName().equals("ROLE_SUPER_ADMIN"))) {
            throw new RuntimeException("Cannot delete super admin user");
        }

        userRepository.delete(user);
    }

    @Override
    @Transactional
    public void enableUser(Long id) {
        User user = userRepository.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("User", "id", id));
        user.setEnabled(true);
        userRepository.save(user);
    }

    @Override
    @Transactional
    public void disableUser(Long id) {
        User user = userRepository.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("User", "id", id));

        // 检查是否为超级管理员
        if (user.getRoles().stream().anyMatch(role -> role.getName().equals("ROLE_SUPER_ADMIN"))) {
            throw new RuntimeException("Cannot disable super admin user");
        }

        user.setEnabled(false);
        userRepository.save(user);
    }

    @Override
    @Transactional
    public void grantAdminRole(Long id) {
        User user = userRepository.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("User", "id", id));

        Role adminRole = roleRepository.findByName("ROLE_ADMIN")
                .orElseThrow(() -> new RuntimeException("Admin role not found"));

        Set<Role> roles = new HashSet<>(user.getRoles());
        roles.add(adminRole);
        user.setRoles(roles);

        userRepository.save(user);
    }

    @Override
    @Transactional
    public void revokeAdminRole(Long id) {
        User user = userRepository.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("User", "id", id));

        // 检查是否为超级管理员
        if (user.getRoles().stream().anyMatch(role -> role.getName().equals("ROLE_SUPER_ADMIN"))) {
            throw new RuntimeException("Cannot revoke super admin role");
        }

        Role adminRole = roleRepository.findByName("ROLE_ADMIN")
                .orElseThrow(() -> new RuntimeException("Admin role not found"));

        Set<Role> roles = user.getRoles().stream()
                .filter(role -> !role.equals(adminRole))
                .collect(Collectors.toSet());
        user.setRoles(roles);

        userRepository.save(user);
    }

    @Override
    @Transactional
    public void resetPassword(Long id) {
        User user = userRepository.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("User", "id", id));

        // 设置默认密码为 "123456"
        user.setPassword(passwordEncoder.encode("123456"));
        userRepository.save(user);
    }

    @Override
    public Page<UserAdminDTO> getInactiveUsers(int days, Pageable pageable) {
        LocalDateTime threshold = LocalDateTime.now().minusDays(days);
        return userRepository.findByLastLoginTimeBefore(threshold, pageable)
                .map(this::convertToAdminDTO);
    }

    @Override
    public Page<UserAdminDTO> getNewUsers(int days, Pageable pageable) {
        LocalDateTime threshold = LocalDateTime.now().minusDays(days);
        return userRepository.findByCreatedAtAfter(threshold, pageable)
                .map(this::convertToAdminDTO);
    }

    private UserAdminDTO convertToAdminDTO(User user) {
        UserAdminDTO dto = new UserAdminDTO();
        dto.setId(user.getId());
        dto.setUsername(user.getUsername());
        dto.setEmail(user.getEmail());
        dto.setNickname(user.getNickname());
        dto.setAvatar(user.getAvatar());
        dto.setBio(user.getBio());
        dto.setEnabled(user.isEnabled());
        dto.setRoles(user.getRoles().stream()
                .map(Role::getName)
                .collect(Collectors.toSet()));
        dto.setArticleCount((int) articleRepository.countByAuthor(user));
        dto.setCommentCount((int) commentRepository.countByUser(user));
        dto.setLastLoginTime(user.getLastLoginTime());
        dto.setLastLoginIp(user.getLastLoginIp());
        dto.setCreatedAt(user.getCreatedAt());
        dto.setUpdatedAt(user.getUpdatedAt());
        return dto;
    }
} 